/*
 * Copyright (C) 2009 Rafael Fernandes
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.phonebooksharing.services.servlets;

import java.awt.Toolkit;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.util.zip.GZIPOutputStream;

import javax.ejb.EJB;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.phonebooksharing.services.ejb3.facade.MessageFacade;
import com.phonebooksharing.services.ejb3.facade.ProfileFacade;
import com.phonebooksharing.services.ejb3.utils.IConstants;
import com.phonebooksharing.services.utils.IOUtilities;
import com.phonebooksharing.services.utils.Thumbnail;

/**
 * Servlet implementation class ImageServlet
 */
public class ImageServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	
    /**
     * @see HttpServlet#HttpServlet()
     */
    public ImageServlet() {
        super();
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//		super.doGet(request, response);
	  //TODO: no get allowed
		doPost(request, response);//getimage goes via get?!?
	}
	
	@EJB
    private ProfileFacade profileFacade;
	
	@EJB
	private MessageFacade messageFacade;

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException {
	    
	    try {
    	    final String ac = request.getParameter("ac");
            if ("p".equalsIgnoreCase(ac)) {// photos
                ObjectInputStream ois = new ObjectInputStream(request.getInputStream());
                final String authItem = (String) ois.readObject();

                ObjectOutputStream oos = new ObjectOutputStream(resp.getOutputStream());

                final String q = request.getParameter("q");
                if("s".equalsIgnoreCase(q)) {
                    oos.writeObject(profileFacade.getSharingImages(authItem));
                } else if("ns".equalsIgnoreCase(q)) {
                    oos.writeObject(profileFacade.getNonSharingImages(authItem));
                } else if("a".equalsIgnoreCase(q)) {//list of all images on the server
                    oos.writeObject(profileFacade.getImageGalleryDeviceIdList(authItem));
                }
                return;//halt
            } else if ("g".equalsIgnoreCase(ac)) {// get image
                final String q = request.getParameter("q");
                final String path = profileFacade.getImagePath(new Long(q));

                writeImageOntoResponse(request, resp, path, Integer.parseInt(request.getParameter("w")), Integer.parseInt(request.getParameter("h")));

            } else if ("gpcf".equalsIgnoreCase(ac)) {// get postcard
                final String q = request.getParameter("q");
                final String path = messageFacade.getPostcardFrontPath(new Long(q));

                writeImageOntoResponse(request, resp, path, Integer.parseInt(request.getParameter("w")), Integer.parseInt(request.getParameter("h")));

            } else if ("gpcb".equalsIgnoreCase(ac)) {// get postcard
                final String q = request.getParameter("q");
                final String path = messageFacade.getPostcardBackPath(new Long(q));

                writeImageOntoResponse(request, resp, path, Integer.parseInt(request.getParameter("w")), Integer.parseInt(request.getParameter("h")));

            } else if ("gic".equalsIgnoreCase(ac)) {// get image and increase counter
                final String q = request.getParameter("q");
                final String path = profileFacade.getImagePathAndIncreaseViewCounter(new Long(q));

                writeImageOntoResponse(request, resp, path, Integer.parseInt(request.getParameter("w")), Integer.parseInt(request.getParameter("h")));
            } else if("u".equalsIgnoreCase(ac)) {//upload image
                final String q = request.getParameter("q");
                final String mt = request.getParameter("mt");
                uploadImage(request, resp, q, mt);
            } else if("gpl".equalsIgnoreCase(ac)) {//get photo list
                ObjectInputStream ois = new ObjectInputStream(request.getInputStream());
                final String authItem = (String) ois.readObject();
                final int page      = new Integer(request.getParameter("p"));
                final int pageSize  = new Integer(request.getParameter("ps"));
                final int contactID = new Integer(request.getParameter("c"));

                ObjectOutputStream oos = new ObjectOutputStream(resp.getOutputStream());
                oos.writeObject(profileFacade.browseImageGallery(authItem, contactID, page, pageSize));
            }
	    } catch (Exception e) {
	        e.printStackTrace();
        }
	}

    private void uploadImage(HttpServletRequest request, HttpServletResponse resp, String imageID, String mimeType) {
        try {
            InputStream in = new DataInputStream(request.getInputStream());
            final String fileName = IConstants.ROOT_FOR_IMAGES + imageID + getMimeTypeExtension(mimeType);
            
            IOUtilities.ensureDirectory(fileName);
            
            final FileOutputStream fos = new FileOutputStream(fileName);
            OutputStream out = new BufferedOutputStream(fos, 4 * 1024);
            byte[] b = new byte[4 * 1024];
            int read;
            while ((read = in.read(b)) != -1) {
                out.write(b, 0, read);
            }
            out.flush();

            profileFacade.setImagePathToImageGallery(new Long(imageID), fileName);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private String getMimeTypeExtension(String mimeType) {
        if("image/jpeg".equalsIgnoreCase(mimeType)) return ".jpg";
        return null;
    }

    private void writeImageOntoResponse(HttpServletRequest request,
                                        HttpServletResponse resp, 
                                        String filename,
                                        int width,
                                        int height) throws IOException {
	    //Get the absolute path of the image
        ServletContext sc = getServletContext();

        // Get the MIME type of the image
        String mimeType = sc.getMimeType(filename);
        if (mimeType == null) {
            System.out.println("Could not get MIME type of "+filename);
            sc.log("Could not get MIME type of "+filename);
            resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            return;
        }

        // Set content type
        resp.setContentType(mimeType);

        // Open the file and output streams
        FileInputStream in=null;
        OutputStream out=null;
        try {
            // Set content size
            File file = new File(filename);
//            resp.setContentLength((int)file.length());
        
            in = new FileInputStream(file);
            
            if(request.getHeader("Accept-Encoding").contains("gzip")) {
                out = new GZIPOutputStream(resp.getOutputStream());
                resp.setHeader("Content-Encoding", "gzip");
            } else {
                out = resp.getOutputStream();
            }
            
            Thumbnail.createThumb(Toolkit.getDefaultToolkit().getImage(filename), width, height, 100, out);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            in.close();
            out.close();
        }
    }
}
